/*
 * Copyright 2005-2008 Pulse Technologies. Tutti i diritti riservati.
 */
package org.obsidianrad.server.services.user.db;


import org.obsidianrad.server.services.user.ObsidianUserDetails;
import org.obsidianrad.server.services.user.rolemanager.RoleManager;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;
import org.springframework.security.BadCredentialsException;
import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
import org.springframework.security.providers.dao.DaoAuthenticationProvider;
import org.springframework.security.userdetails.UserDetails;

/**
 * 
 * @author Eligio Colutta
 * @version $Rev: 21 $
 * @lastautorcommit $Author: eliosh $
 * @lastdatecommit $Date: 2010-01-06 12:09:45 +0100(mer, 06 gen 2010) $
 */
public class ObsidianAuthenticationProvider extends DaoAuthenticationProvider {

	private RoleManager roleManager;
	private String pwdSuffix;
	
	/* (non-Javadoc)
	 * @see org.springframework.security.providers.dao.AbstractUserDetailsAuthenticationProvider#createSuccessAuthentication(java.lang.Object, org.springframework.security.Authentication, org.springframework.security.userdetails.UserDetails)
	 */
	@Override
	protected Authentication createSuccessAuthentication(Object principal, Authentication authentication, UserDetails user) {
        // Ensure we return the original credentials the user supplied,
        // so subsequent attempts are successful even with encoded passwords.
        // Also ensure we return the original getDetails(), so that future
        // authentication events after cache expiry contain the details
        UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(principal, authentication.getCredentials(), user.getAuthorities());
        
        //caricare le preferenze di default, fare una fusione con quelle utente e metterle come dettagli dell'auth
        result.setDetails( ((ObsidianUserDetails)user).getPreferences() );
        return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.springframework.security.providers.dao.DaoAuthenticationProvider#additionalAuthenticationChecks(org.springframework.security.userdetails.UserDetails,
	 *      org.springframework.security.providers.UsernamePasswordAuthenticationToken)
	 */
	@Override
	protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
		Object salt = null;

		if (this.getSaltSource() != null) {
			salt = this.getSaltSource().getSalt(userDetails);
		}

		if (authentication.getCredentials() == null) {
			throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"),
					this.isIncludeDetailsObject() ? userDetails : null);
		}

		String presentedPassword = authentication.getCredentials().toString();

		// controllare se l'utente con il flag di superadmin ha messo la superpwd
		ObsidianUserDetails uDetails =  (ObsidianUserDetails) userDetails;
		boolean tryToSuper = false;
		if(uDetails.isCanSuperAdmin()){
			String newPresentedPassword = removePwdSuffix(presentedPassword); // eliminare il pezzo di superpasswd
			if(newPresentedPassword.equals(presentedPassword)){
				// sta effettuando il login in maniera normale, non facciamo nulla
			}else{
				// sta effettuando il login come super utente
				tryToSuper = true;
				presentedPassword = newPresentedPassword;
			}
		}
		
		if (!this.getPasswordEncoder().isPasswordValid(userDetails.getPassword(), presentedPassword, salt)) {
			throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"),
					this.isIncludeDetailsObject() ? userDetails : null);
		}
		
		// a questo punto il login è andato a buon fine.
		// Facciamo il controllo che se ha fatto il login con la superpwd, gli dobbiamo iniettare tutti i ruoli possibili, per tutti i contesti
		if(tryToSuper){
			uDetails.setAuthorities(roleManager.getGrantedAuthorities());
		}
	}

	/**
	 * Rimuovi il suffisso della superpassword
	 * @param presentedPassword 
	 * @return
	 */
	private String removePwdSuffix(String presentedPassword){
		if(presentedPassword.contains(getPwdSuffix())){
			return presentedPassword.substring(0, presentedPassword.indexOf(getPwdSuffix()));
		}else{
			return presentedPassword;
		}
	}

	/**
	 * @return the pwdSuffix
	 */
	public String getPwdSuffix() {
		return pwdSuffix;
	}

	/**
	 * @param pwdSuffix the pwdSuffix to set
	 */
	public void setPwdSuffix(String pwdSuffix) {
		this.pwdSuffix = pwdSuffix;
	}

	/**
	 * @return the roleManager
	 */
	public RoleManager getRoleManager() {
		return roleManager;
	}

	/**
	 * @param roleManager the roleManager to set
	 */
	public void setRoleManager(RoleManager roleManager) {
		this.roleManager = roleManager;
	}

}
